﻿using System;
using System.Reflection;

namespace System
{
	public sealed class DomainHelper : IDisposable
	{
		private readonly AppDomain _domain;
		private const string ShadowCopyFilesParameter = "true";

		public DomainHelper(string name, string path)
		{
			AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;

			var setup = new AppDomainSetup
			{
				ShadowCopyDirectories = path,
				ShadowCopyFiles = ShadowCopyFilesParameter,
				ApplicationBase = path,
				ApplicationName = name
			};

			_domain = AppDomain.CreateDomain(name, AppDomain.CurrentDomain.Evidence, setup);
		}

		public object CreateInstanceFromAndUnwrap(string location, string typeName)
		{
			return _domain.CreateInstanceFromAndUnwrap(location, typeName);
		}

		public object CreateInstanceAndUnwrap(string location, string typeName)
		{
			return _domain.CreateInstanceAndUnwrap(location, typeName);
		}

		public void Dispose()
		{
			AppDomain.Unload(_domain);
			AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomainAssemblyResolve;
		}

		static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
		{
			return Assembly.GetExecutingAssembly()
				.If(a => a.FullName == args.Name,
					a => a,
					_ => Assembly.Load(args.Name));
		}
	}
}
